home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i189: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part11/12
- Message-ID: <12980@xanth.cs.odu.edu>
- Date: 28 Jun 90 12:23:40 GMT
- Sender: news@cs.odu.edu
- Reply-To: Matt Dillon <@uunet.uu.net:overload!dillon>
- Lines: 1532
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
- Posting-number: Volume 90, Issue 189
- Archive-name: unix/uucp-1.06d/part11
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 11 (of 12)."
- # Contents: uucp2/src/uucico/uucico.c
- # Wrapped by tadguy@xanth on Thu Jun 28 08:21:37 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'uucp2/src/uucico/uucico.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'uucp2/src/uucico/uucico.c'\"
- else
- echo shar: Extracting \"'uucp2/src/uucico/uucico.c'\" \(33705 characters\)
- sed "s/^X//" >'uucp2/src/uucico/uucico.c' <<'END_OF_FILE'
- X
- X/*
- X * UUCICO.C
- X *
- X * $Header: Beta:src/uucp/src/uucico/RCS/uucico.c,v 1.1 90/02/02 11:56:01 dillon Exp Locker: dillon $
- X *
- X * (C) Copyright 1987 by John Gilmore.
- X * Copying and use of this program are controlled by the terms of the Free
- X * Software Foundation's GNU Emacs General Public License.
- X *
- X * Derived from:
- X * i[$]uuslave.c 1.7 08/12/85 14:04:20
- X * which came from the ACGNJ BBS system at +1 201 753 9758. Original
- X * author unknown.
- X *
- X * Ported to Amiga by William Loftus
- X * Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
- X * Additional Major Changes (c)Copyright 1989 by Matthew Dillon, All rights reserved
- X *
- X * 14-Oct-89, moved modem_init() to before poll_sys.
- X *
- X * -r option (-r1 does a call out to all systems we have mail for)
- X * -D[EVICE] dev sets serial device name (automatic from Getty)
- X * -U[NIT] unit sets unit name (automatic from Getty)
- X * -h0 Ignore CD (carrier detect)
- X * -7
- X */
- X
- X
- X#include "includes.h" /* System include files, system dependent */
- X#include "uucp.h" /* Uucp definitions and parameters */
- X#include <log.h>
- X#include "version.h"
- X
- XPrototype int getname(int);
- XPrototype int get_proto(void);
- XPrototype int instr(char *, int);
- XPrototype int twrite(const char *, int);
- XPrototype void xlat_str(char *, char *);
- XPrototype int read_ctl(void);
- XPrototype int do_outbound(void);
- XPrototype int call_system(char *, int);
- XPrototype int call_sysline(char *);
- XPrototype int do_session(int);
- XPrototype int top_level(int);
- XPrototype int do_one_slave(void);
- XPrototype int do_one_master(void);
- XPrototype int yesno(char, int, int);
- XPrototype int host_send_file(char *);
- XPrototype int host_receive_file(char *);
- XPrototype int local_send_file(char *, int *);
- XPrototype int local_receive_file(void);
- XPrototype int receive_file(FILE *, char *, char *, char *, int);
- XPrototype int send_file(FILE *);
- X
- X#define MAX_FLAGS 40
- X
- Xextern int errno;
- X
- XIDENT(".10");
- X
- Xstatic char *Copyright = COPYRIGHT;
- X
- Xchar ttynam[NAMESIZE], /* Name of tty we use as serial port */
- X srcnam[NAMESIZE], /* Source file name */
- X dstnam[NAMESIZE], /* Dest file name */
- X who[NAMESIZE] = "-", /* Who sent the file */
- X flags[MAX_FLAGS], /* Flags from file xfer cmd */
- X temp[NAMESIZE]; /* Temp file name */
- X
- Xint ourpid = 0, /* Our process ID */
- X ignore_time_restrictions = 0, /* Call out even if L.sys sez no */
- X mode; /* File mode from file xfer cmd */
- X
- Xchar host_name[MAX_HOST] = "AmigaUUCP"; /* Other guy's host name */
- Xchar our_name[MAX_HOST]; /* Our uucp hostname, set from usenet.ctl */
- Xchar path[128];
- Xint debug = -1; /* -1 indicates not set by command line or ctl file */
- Xint f_wait = 0; /* wait for a call (-w) or calls (-w -e) after outbnd */
- Xint loop = 0; /* Loop accepting logins if tty name specified */
- Xint curtemp = 0;
- Xint Overide = 0; /* overide modem protocol */
- Xint Getty = 0; /* -Getty initiated */
- Xint IgnoreCD= 0; /* xgetc() should ignore carrier? */
- Xint OurNameOv= 0;
- Xint WindowOne= 0;
- Xint SevenWire= 0;
- Xint XDebug = 0; /* do not pass debug parameter to remote */
- X
- X#define MAX_STRING 200 /* Max length string to send/expect */
- X
- X#define MSGO2IDX 7
- X
- X/* We print these prompts */
- X
- Xchar msgo0[] = "login: ";
- Xchar msgo1[] = "Password:";
- Xchar msgo2[10+MAX_HOST] = { "\20Shere" }; /* NO = */
- Xchar msgo3[] = "\20ROK\0";
- Xchar msgo3a[]= "\20P";
- Xchar msgo3b[]= "\20Pg\0";
- Xchar msgo4[] = "\20OOOOOOO\0";
- X
- X/* We expect to receive these strings */
- X
- Xchar msgi0[] = "uucp\r";
- Xchar msgi1[] = "s8000\r";
- X/* char msgi2[] = "\20S*\0"; We now scan it specially FIXME */
- Xchar msgi3[] = "\20Ug\0";
- Xchar msgi4[] = "OOOOOO";
- X
- X/*
- X * Protocol switch data structure
- X */
- X
- X#define turnon gturnon
- X#define rdmsg grdmsg
- X#define wrmsg gwrmsg
- X#define rddata grddata
- X#define wrdata gwrdata
- X#define turnoff gturnoff
- X
- Xint
- Xgetname(isshere)
- Xint isshere;
- X{
- X int data, count = 0;
- X static char msgi[MAX_STRING+SLOP]; /* Incoming trash buffer */
- X
- X /* Read data until null character */
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X data &= 0x7F;
- X if (data == 020)
- X break;
- X }
- X if (data == EOF)
- X return FAIL;
- X
- X while ((data = xgetc(BYTE_TO)) != EOF && (data & 0x7F)) {
- X data &= 0x7F;
- X if (count == 0 && data != 'S')
- X continue;
- X if (count > sizeof(msgi) - 2)
- X continue;
- X msgi[count++] = (char)data;
- X }
- X msgi[count] = 0;
- X
- X if (debug > 8)
- X printf("GETNAME MSG (%d): %s\n", count, msgi);
- X
- X if (msgi[0] != 'S')
- X return FAIL;
- X if (isshere) {
- X for (count = 1; msgi[count] && msgi[count] != '='; ++count);
- X if (msgi[count] == '=')
- X ++count;
- X } else {
- X count = 1;
- X }
- X if (msgi[count]) {
- X if (debug > 8)
- X printf("Compare host names: '%s' '%s'\n", host_name, msgi + count);
- X strcpy (host_name, msgi + count);
- X }
- X strtok(host_name, " \t"); /* put \0 after hostname */
- X if (debug > 8)
- X printf("Hostname is '%s'\n", host_name);
- X return SUCCESS;
- X}
- X
- X/*
- X * get_proto() checks the list of protos given by the foriegn machine
- X * checking for 'g' (which is the only proto we have). Use only in master
- X * mode.
- X */
- X
- Xint
- Xget_proto()
- X{
- X int data;
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X data &= 0x7F;
- X if (data == 0)
- X break;
- X if (data == 'g')
- X return(SUCCESS);
- X }
- X return FAIL;
- X}
- X
- X/*
- X * Medium level input routine.
- X *
- X * Look for an input string for the send-expect sequence.
- X * Return 0 for matching string, 1 for timeout before we found it.
- X * FIXME: we only time out if the other end stops sending. If it
- X * keeps sending, we keep listening forever.
- X */
- X
- Xinstr(s, n)
- Xchar *s;
- Xint n;
- X{
- X int data,count,j;
- X int i;
- X static char msgi[512]; /* Incoming trash buffer */
- X
- X count = 0;
- X
- X if (debug > 8) {
- X printf("Expecting ");
- X for (i = 0; i < n; i++)
- X printc(s[i]);
- X printf("\n");
- X }
- X
- X while ((data = xgetc(BYTE_TO)) != EOF) {
- X msgi[count++] = (char)data & 0x7F;
- X
- X if (count == sizeof(msgi)) { /* throw away first half */
- X count = sizeof(msgi) / 2;
- X bcopy(msgi + sizeof(msgi) / 2, msgi, sizeof(msgi) / 2);
- X }
- X
- X if (count >= n) {
- X for (i = n - 1, j = count - 1; i >= 0; i--, j--) {
- X if (*(s+i) != msgi[j])
- X break;
- X }
- X if (i < 0) {
- X if (debug > 8)
- X printf("\n");
- X return(0);
- X }
- X }
- X }
- X
- X if (debug > 8)
- X printf("\n");
- X msgi[count] = (char)0;
- X return(1);
- X}
- X
- X/*
- X * Debugging hack for stuff written to the modem.
- X */
- X
- Xint
- Xtwrite(s, n)
- Xconst char *s;
- Xint n;
- X{
- X int i;
- X
- X if (debug > 8) {
- X printf("Wrote: ");
- X for (i = 0; i < n; i++)
- X printc(s[i]);
- X printf("\n");
- X }
- X return xwrite(s, n);
- X}
- X
- X/*
- X * MAIN ROUTINE.
- X *
- X * This is called at program startup. It parses the arguments to the
- X * program (if any) and sets up to receive a call on the modem.
- X *
- X * If there are no arguments, we assume the caller is already on standard
- X * input, waiting to do uucp protocols (past the login prompt), and we
- X * just handle one caller.
- X *
- X * If there is an argument, it is the name of the tty device where we
- X * should listen for multiple callers and handle login and password.
- X */
- X
- Xvoid
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i;
- X char *poll_sys = (char *)NULL; /* System name to poll, or none */
- X short rmode = 0; /* 1 = master, 0 = slave */
- X
- X LogProgram = "uucico";
- X LogHost = host_name;
- X LogWho = who;
- X
- X onbreak(sigint);
- X
- X /* FIXME, use getopt */
- X /* scan command line arguments, kinda kludgy but it works */
- X
- X for (i = 1; i < argc; ++i) {
- X if (argv[i][0] != '-') {
- X printf("uucico: warning, extra args ignored: %s\n", argv[i]);
- X break;
- X }
- X switch (argv[i][1]) {
- X case 'N':
- X strcpy(our_name, argv[i] + 2);
- X OurNameOv = 1;
- X break;
- X case 'D': /* Serial Device */
- X {
- X extern char *DeviceName;
- X DeviceName = argv[++i];
- X }
- X break;
- X case 'U': /* Serial Unit */
- X {
- X extern long DeviceUnit;
- X DeviceUnit = atoi(argv[++i]);
- X }
- X break;
- X case 'g':
- X case 'G':
- X Getty = 1;
- X break;
- X case 'h':
- X IgnoreCD = atoi(argv[i] + 2);
- X break;
- X case 'w':
- X ++f_wait;
- X break;
- X case 'r':
- X rmode = atoi(&argv[i][2]);
- X break;
- X case 'X':
- X XDebug = 1;
- X case 'x':
- X debug = atoi(&argv[i][2]);
- X LogLevel = debug;
- X LogToStdout = 1;
- X printf("uucico: debug level set to %d\n", debug);
- X break;
- X case 'o':
- X Overide = 1;
- X break;
- X case 'n':
- X WindowOne = 1; /* force windowing mode to size=1 */
- X break;
- X case 'S':
- X ignore_time_restrictions++;
- X case 's':
- X poll_sys = &argv[i][2];
- X break;
- X case 'e':
- X ++loop;
- X break;
- X /* Is -t needed for MSDOS? Why? -- hoptoad!gnu */
- X case 't':
- X curtemp++;
- X printf("uucico: using ~uutemp.$$$ for temp file\n");
- X break;
- X case '7':
- X SevenWire = 1;
- X break;
- X default:
- X printf("uucico: warning, bad flag %s\n", argv[i]);
- X break;
- X }
- X }
- X
- X /* If argument provided, use it as name of comm port */
- X
- X /* FIXME, this needs some thought. */
- X
- X getcwd(path,128);
- X if (chdir(GetConfigDir(UUSPOOL))) {
- X perror("Can't chdir to Spool directory");
- X exit(2);
- X }
- X
- X read_ctl();
- X
- X /*
- X * If running via getty/login, our debug stdout had better
- X * go to a file, not to the usual stdout!
- X */
- X
- X if (debug > 0 && Getty) {
- X freopen("T:uuslave.log", "a", stdout);
- X }
- X
- X /*setvbuf(stdout, NULL, _IOLBF, 0);*/
- X
- X /* Timestamp the long debug log */
- X
- X if (debug > 0) {
- X long clock;
- X
- X time(&clock);
- X printf("\014\nuuslave log on tty '%s' starting %s\n",
- X ttynam, ctime(&clock));
- X }
- X
- X /* Log our presence so we humans reading the logs can find the
- X entries created by uuslave. */
- X
- X ulog(-1, "Startup %s", VERSION);
- X
- X amiga_setup();
- X
- X modem_init();
- X
- X if (poll_sys) {
- X if (*poll_sys == '\0')
- X poll_sys = (char *)NULL;
- X call_system(poll_sys, rmode);
- X if (!f_wait)
- X goto end;
- X } else {
- X if (rmode) {
- X do_outbound();
- X if (!f_wait)
- X goto end;
- X }
- X }
- X
- X do {
- X /*
- X * Set up serial channel, wait for incoming call.
- X */
- X DEBUG(0, "\nRestarting\n", 0);
- X
- X if (Getty == 0 && Overide == 0)
- X openline();
- X
- X do_session(Getty);
- X
- X hangup();
- X DEBUG(0, "\nEnd of call\n", 0);
- X } while (loop && !Getty);
- X
- Xend:
- X cleanup();
- X}
- X
- X/*
- X * translate embedded escape characters
- X */
- X
- Xvoid
- Xxlat_str(msg, out)
- Xchar *msg;
- Xchar *out;
- X{
- X int i = 0;
- X int cr = 1;
- X /*int j = 0;*/
- X
- X while (msg[i]) {
- X if (msg[i] == '\\') {
- X switch (msg[++i]) {
- X case 'r': /* carriage return */
- X twrite("\r", 1);
- X /*out[j++] = 0x0d;*/
- X break;
- X case 'n': /* line feed */
- X twrite("\n", 1);
- X /*out[j++] = 0x0a;*/
- X break;
- X case '\\': /* back slash */
- X twrite("\\", 1);
- X /*out[j++] = '\\';*/
- X break;
- X case 't': /* tab */
- X twrite("\t", 1);
- X /*out[j++] = '\t';*/
- X break;
- X case 'b':
- X SendBreak();
- X break;
- X case 'd': /* delay */
- X Delay(180);
- X break;
- X case 's': /* space */
- X twrite(" ", 1);
- X /*out[j++] = ' ';*/
- X break;
- X case 'c': /* no CR at end */
- X cr = 0;
- X break;
- X default: /* don't know so skip it */
- X break;
- X }
- X ++i;
- X } else {
- X twrite(msg + i, 1);
- X ++i;
- X /*out[j++] = msg[i++];*/
- X }
- X }
- X if (cr) {
- X twrite("\r", 1);
- X /*out[j++] = 0x0d;*/
- X }
- X /*out[j] = '\0';*/
- X}
- X
- X/*
- X * Read the control file and grab a few parameters.
- X */
- X
- Xint
- Xread_ctl()
- X{
- X char *nodename = FindConfig(NODENAME);
- X char *debugstr = FindConfig(DEBUGNAME);
- X
- X if (nodename && OurNameOv == 0)
- X strcpy(our_name, nodename);
- X if (debugstr && debug < 0)
- X debug = atoi(debugstr);
- X return (1);
- X}
- X
- X/*
- X * Search spool queues for work, call the systems we need to call.
- X */
- X
- Xint
- Xdo_outbound()
- X{
- X return call_system((char *)NULL, 1);
- X}
- X
- X/*
- X * Call a specific system, or all systems that have work pending.
- X */
- X
- Xint
- Xcall_system(sys, ifworkpend)
- Xchar *sys;
- X{
- X FILE *lsys;
- X static char buf[MAX_LSYS];
- X static char sysnam[MAX_HOST];
- X static char prev_name[MAX_HOST];
- X int called = FAIL;
- X
- X /*
- X * Unix uucico just reads the directory, and calls the systems
- X * in the order of the files in the directory. We want more
- X * control than that, though I'm not sure that L.sys order is
- X * best either. For example, in the first call after 11PM,
- X * I'd like to call the sites that haven't been callable before
- X * 11PM first, and finish up with the ones I've been able to call
- X * all day. FIXME.
- X */
- X
- X if (! (lsys = fopen(MakeConfigPath(UULIB, "L.sys"), "r"))) {
- X DEBUG(0, "uucico: can't open L.sys, errno %d\n", errno);
- X return 0;
- X }
- X sysnam[0] = '\0'; /* Initially, no previous sys */
- X
- X /* Once per system in L.sys... */
- X /* FIXME, handle continuation lines (trailing "\") */
- X
- X while (fgets(buf, sizeof buf, lsys)) {
- X if (buf[0] == '#' || buf[0] == '\n')
- X continue;
- X
- X /*
- X * Grab the system name. If same as previous, and
- X * the previous call worked, skip it.
- X */
- X
- X strcpy(prev_name, sysnam);
- X (void) sscanf(buf, "%s", sysnam);
- X if (!strcmp(sysnam, prev_name)) {
- X if (called == SUCCESS)
- X continue;
- X }
- X
- X /*
- X * If a system name was specified, skip til we find it
- X * If none was specified, only call if there is work.
- X */
- X
- X if (sys) {
- X if (strcmp(sys, sysnam) != 0)
- X continue;
- X if (ifworkpend && !work_scan(sysnam)) {
- X ulog(-1, "No work for system %s", sysnam);
- X called = SUCCESS;
- X continue;
- X }
- X } else {
- X DEBUG(3,"searching for outbound to %s\n", sysnam);
- X if (!work_scan(sysnam)) {
- X DEBUG(3,"no work for %s\n", sysnam);
- X called = SUCCESS; /* Don't try further */
- X continue;
- X }
- X DEBUG(2, "uucico: found work for %s\n", sysnam);
- X }
- X
- X called = call_sysline(buf);
- X
- X if (called == SUCCESS && sys)
- X break;
- X }
- X
- X fclose(lsys);
- X if (called == FAIL && sys)
- X DEBUG(0, "Could not call system %s\n", sys);
- X return 0;
- X}
- X
- X/*
- X * Call out to a system, given its L.sys line.
- X */
- X
- Xint
- Xcall_sysline(lsysline)
- Xchar *lsysline;
- X{
- X static char tempname[MAX_HOST + 30 + SLOP];
- X static char strbuf[MAX_STRING+SLOP];
- X char *sysnam,
- X *times,
- X *acu,
- X *sbaud,
- X *telno,
- X *send,
- X *expct;
- X int baud;
- X
- X who[0] = '-'; who[1] = '\0'; /* No user now (for logit) */
- X
- X /* FIXME, use the values it is ignoring here */
- X
- X sysnam = strtok(lsysline, " \t");
- X times = strtok(NULL, " \t"); /* Time */
- X acu = strtok(NULL, " \t"); /* ACU */
- X sbaud = strtok(NULL, " \t"); /* Baud */
- X telno = strtok(NULL," \t"); /* phone*/
- X
- X strcpy(host_name, sysnam);
- X
- X if (ignore_time_restrictions == 0) {
- X if (CheckTimeRestrictions(times) == FAIL) {
- X ulog(-1, "Wrong Time To Call %s", sysnam);
- X return(FAIL);
- X }
- X }
- X
- X baud = atoi(sbaud);
- X
- X /* FIX ME, acu not implemented ? */
- X DEBUG(4, "Opening outgoing line %s\n", acu);
- X if (openout(acu, baud) != SUCCESS)
- X return FAIL;
- X
- X if (Overide == 0) {
- X if (dial_nbr(telno)) {
- X ulog(-1, "FAILED call to %s", host_name);
- X return FAIL;
- X }
- X }
- X
- X /* FIXME, log tty, baud rate, ... */
- X ulog(-1, "DIALED %s", host_name);
- X
- X /*
- X * Process send-expect strings.
- X * FIXME, deal with "-", BREAK, etc.
- X */
- X
- X while (send = (char*)strtok((char *)NULL, " \t")) {
- X if (send[0] != '"' || send[1] != '"' || send[2] != '\0') {
- X if (instr(send, strlen(send)))
- X goto bort1;
- X }
- X
- X if (expct = (char*)strtok((char *)NULL, " \t")) {
- X /* FIXME secondary strings, e.g. ogin:-EOT-ogin: */
- X xlat_str(expct, strbuf);
- X
- X /*twrite(strbuf, strlen(strbuf));*/
- X }
- X }
- X
- X /*
- X * FIXME, there should be a way to detect login/passwd
- X * failure here and keep doing the script rather than
- X * continuing to expect Shere at another login: prompt.
- X */
- X
- X ulog(-1, "SUCCEEDED call to %s", host_name);
- X
- X
- X if (getname(1)) /* get name */
- X goto bort1;
- X /* send response */
- X sprintf(tempname, "\20S%s -Q0 -x%d\0", our_name, (XDebug) ? 0 : debug);
- X twrite(tempname, strlen(tempname)+1); /* Including null */
- X
- X /* wait for ok message, wait for protocol request
- X * send protocol 'g' response */
- X /* FIXME, we don't actually wait for the ROK message, since
- X * it is immediately followed by the Pprotos message. We
- X * currently just look for a Pg message. This needs work.
- X * FIXME, WE CAN'T TALK TO SITES THAT SUPPORT more than 'g'.
- X */
- X
- X if (instr(msgo3a, sizeof(msgo3a)-1)) {
- X if (!get_proto())
- X goto bort1;
- X }
- X
- X
- X twrite( msgi3, sizeof(msgi3)-1);
- X
- X ResetGIO(); /* reset GIO protocol */
- X
- X if (turnon(1))
- X goto bort1;
- X
- X ulog(-1, "OK Startup");
- X
- X top_level(1);
- X hangup();
- X return SUCCESS;
- X
- Xbort1:
- X hangup();
- X return FAIL;
- X}
- X
- X/* Handle a single uucp [slave] login session */
- X
- Xint
- Xdo_session(ontheline)
- Xint ontheline;
- X{
- X if (ontheline == 0) {
- X /* output login request, verify uucp */
- X twrite(msgo0,sizeof(msgo0)-1);
- X if (instr(msgi0,sizeof(msgi0)-1)) {
- X printf("uucico: invalid login name\n");
- X goto bort;
- X }
- X
- X /* output password request, verify s8000 */
- X twrite(msgo1,sizeof(msgo1)-1);
- X if (instr(msgi1,sizeof(msgi1)-1)) {
- X printf("uucico: invalid password\n");
- X goto bort;
- X }
- X
- X printf("uucico: correct login\n");
- X }
- X
- X /*
- X * send Shere=<myhost>
- X *
- X * Apparently mac UUCP has a bug that only allows 7
- X * char host names, and it fails if it gets shere=<myhost>
- X * where <myhost> is > 7 chars.
- X */
- X
- X /*strcpy(msgo2 + MSGO2IDX, our_name);*/
- X twrite(msgo2,strlen(msgo2)+1);
- X
- X /*
- X * get \020S<host> -Qn n (??)
- X */
- X
- X if (getname(0))
- X goto bort;
- X
- X /* output ok message, output protocol request, wait for response */
- X
- X twrite(msgo3,sizeof(msgo3)-1);
- X
- X /* FIXME, make the protocol list here, and use it */
- X twrite(msgo3b,sizeof(msgo3b)-1);
- X if (instr(msgi3,sizeof(msgi3)-1))
- X goto bort;
- X
- X ResetGIO(); /* reset GIO protocol */
- X
- X if (turnon(0))
- X goto bort;
- X
- X ulog(-1, "OK Startup");
- X top_level(0);
- X
- Xbort:
- X if (debug > 0)
- X printf("uucico: call complete\n");
- X return (1);
- X}
- X
- X/*
- X * Handle transactions "at top level", as Unix uucp's debug log says.
- X *
- X * As master, we scan our queues for work and send requests to the
- X * other side. When done, we send a hangup request and switch to slave mode.
- X *
- X * As slave, we accept requests from the other side; when it is done,
- X * it sends a hangup request, and we switch to master mode, if we have
- X * any work queued up for that system.
- X *
- X * This repeats as long as either side has work to do. When all the
- X * queued work is done, we agree to hang up, terminate the packet protocol,
- X * and return to the caller. (We still haven't hung up the phone line yet.)
- X *
- X * A curious feature of the hangup protocol is that it is not a simple
- X * question-answer. The master says "H", asking about hangup. The
- X * slave responds "HY" saying OK. The master then says "HY" also,
- X * then both of them hang up. Maybe this is to make sure the first HY
- X * got ack'ed? Anyway, an "H" is reported as HANGUP and an "HY" as
- X * HANGNOW. After we send an HY, we go back to listening for commands;
- X * if the master sends something other than HY, we'll do it.
- X */
- X
- X#define HANGUP 2 /* Signal to switch master/slave roles */
- X#define HANGNOW 3 /* Signal to hang up now */
- X#define COPYFAIL 4 /* File copy failed */
- X
- Xint
- Xtop_level(master_mode)
- Xint master_mode;
- X{
- X static char buf[MAXMSGLEN]; /* For hangup responses */
- X
- X
- X if (master_mode) {
- X (void) work_scan(host_name); /* Kick off queue scan */
- X goto master;
- X }
- X
- X for (;;) {
- X slave: /* SLAVE SIDE */
- X for (;;) {
- X DEBUG(4, "*** TOP *** - slave\n", 0);
- X switch (do_one_slave()) {
- X case SUCCESS:
- X break;
- X case FAIL:
- X return FAIL;
- X case HANGUP:
- X if (work_scan(host_name)) {
- X if (wrmsg("HN"))
- X return FAIL;
- X goto master;
- X } else {
- X if (wrmsg("HY"))
- X return FAIL;
- X break; /* go to master mode */
- X }
- X case HANGNOW:
- X goto quit;
- X }
- X }
- X master: /* MASTER SIDE */
- X for (;;) {
- X DEBUG(4, "*** TOP *** - master\n", 0);
- X switch (do_one_master()) {
- X case SUCCESS:
- X break;
- X case FAIL:
- X return FAIL;
- X case HANGUP:
- X /* We wrote an H command, what's the resp? */
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X return FAIL;
- X }
- X if (buf[0] != 'H')
- X return FAIL;
- X if (buf[1] == 'N')
- X goto slave;
- X else {
- X /* Write the final HY */
- X if (wrmsg("HY"))
- X return FAIL;
- X goto quit;
- X }
- X }
- X }
- X }
- X
- Xquit:
- X /* Shut down the packet protocol */
- X
- X turnoff();
- X
- X /* Write the closing sequence */
- X
- X twrite(msgo4, sizeof(msgo4)-1);
- X (void) instr(msgi4, sizeof(msgi4)-1);
- X
- X twrite(msgo4, sizeof(msgo4)-1);
- X
- X strcpy(who, "-");
- X ulog(-1, "OK Conversation complete");
- X
- X return SUCCESS; /* Go byebye */
- X}
- X
- X/*
- X * We are slave; get a command from the other side and execute it.
- X *
- X * Result is SUCCESS, FAIL, HANGUP, or HANGNOW.
- X */
- X
- Xint
- Xdo_one_slave()
- X{
- X static char msg[MAXMSGLEN]; /* Master's message to us */
- X
- X /* Get master's command */
- X if (rdmsg(msg, MAXMSGLEN) != SUCCESS)
- X return FAIL;
- X
- X /* Print it for easy debugging */
- X DEBUG(5,"\nCommand: %s\n\n", msg);
- X
- X switch (msg[0]) {
- X case 'S':
- X if (msg[1] != ' ')
- X break;
- X return host_send_file(msg);
- X case 'R':
- X if (msg[1] != ' ')
- X break;
- X return host_receive_file(msg);
- X case 'X':
- X /*
- X * Cause uuxqt to run (on certain files?)
- X * See Protocol.doc for sketchy details.
- X */
- X break;
- X case 'H':
- X if (msg[1] == '\0') return HANGUP;
- X if (msg[1] == 'Y') return HANGNOW;
- X if (msg[1] == 'N') return SUCCESS; /* Ignore HN to slave */
- X break;
- X }
- X
- X /* Unrecognized packet from the other end */
- X
- X DEBUG(0, "Bad control packet refused: %s\n", msg);
- X if (yesno(msg[0], 0, 0)) /* FIXME: return error code */
- X return FAIL;
- X return SUCCESS;
- X}
- X
- X/*
- X * Do one piece of work as master.
- X *
- X * FIXME: we don't handle the flags, e.g. -c, properly!
- X *
- X * Now only dequeues queue file if all transfers were successful.
- X */
- X
- Xint
- Xdo_one_master()
- X{
- X FILE *fd;
- X char *sname;
- X char cmnd[1]; /* Command character */
- X static char buf[256];
- X int fail = SUCCESS;
- X int failaccum = 0;
- X int num;
- X int delmeflag;
- X static char notify[NAMESIZE]; /* A bit large...FIXME */
- X char *delList[16]; /* delete files list */
- X short di = 0;
- X
- X /* FIXME: do the notify stuff */
- X
- X sname = work_next();
- X if (!sname) {
- X /* No more work, time to hang up. */
- X if (wrmsg("H"))
- X return FAIL;
- X return HANGUP;
- X }
- X
- X DEBUG(2, "Request file %s\n", sname);
- X
- X LockFile(sname);
- X
- X fd = fopen(sname, "r");
- X if (fd == NULL) {
- X UnLockFile(sname);
- X DEBUG(0, "uucico: couldn't open %s\n", sname);
- X return SUCCESS;
- X }
- X
- X while (fgets(buf, sizeof buf, fd)) {
- X DEBUG(3, "Queued request: %s", buf);
- X
- X if (buf[1] != ' ')
- X goto badnum;
- X
- X num = sscanf(buf, "%s %s %s %s %s %s %o\n",
- X cmnd, srcnam, dstnam, who, flags, temp, &mode, notify
- X );
- X
- X switch (cmnd[0]) {
- X case 'S':
- X if (num < 7 || num > 8)
- X goto badnum;
- X fail = local_send_file(buf, &delmeflag);
- X if (delmeflag) {
- X if (di == sizeof(delList)/sizeof(delList[0])) {
- X ulog(-1, "Too many source files in Cmd file! %s", sname);
- X } else {
- X delList[di] = malloc(strlen(temp) + 1);
- X strcpy(delList[di], temp);
- X ++di;
- X }
- X }
- X break;
- X case 'R':
- X if (num != 5) {
- X if (debug > 7)
- X printf("Invalid scanf %d/5 :%s:%s:%s\n", num, cmnd, srcnam, dstnam);
- X goto badnum;
- X }
- X fail = local_receive_file();
- X break;
- X default:
- X badnum:
- X DEBUG(0, "Unknown/invalid queued request: %s\n", buf);
- X ++fail;
- X break;
- X }
- X if (fail != SUCCESS)
- X ++failaccum;
- X
- X /* FIXME, what does uucp do if one of N xfers fails? */
- X
- X if (fail == FAIL) {
- X ulog(-1, "Error in work file %s", sname);
- X ulog(-1, "Bad line is: %s", buf);
- X }
- X }
- X fclose(fd);
- X
- X /*
- X * If we successfuly copied everything zap the queue file
- X * and any local data files...
- X */
- X
- X if (failaccum == 0) {
- X while (di) {
- X --di;
- X remove(delList[di]);
- X free(delList[di]);
- X }
- X fail = remove(sname);
- X UnLockFile(sname);
- X if (fail != 0) {
- X ulog(-1, "Unable to remove work file %s", sname);
- X DEBUG(0, "Can't remove, errno %d\n", errno);
- X } else {
- X DEBUG(4, "Removed work file %s\n", sname);
- X }
- X } else {
- X UnLockFile(sname);
- X }
- X return SUCCESS;
- X}
- X
- X/* Send a "yes or no" packet with character 'c'. */
- X
- Xint
- Xyesno(c, true, err)
- Xchar c;
- Xint true;
- Xint err;
- X{
- X char buf[21];
- X
- X buf[0] = c;
- X buf[1] = true? 'Y': 'N';
- X buf[2] = 0;
- X if (err && !true)
- X sprintf(buf+2,"%d", err);
- X
- X return wrmsg(buf);
- X}
- X
- X/*
- X * SLAVE MODE, Master wishes to send a file to us
- X *
- X * SECURITY: If file is not in list of allowed directories
- X * disallow transfer. UUSPOOL: is always in the
- X * list.
- X *
- X * If file is for UUSPOOL: (the current dir), disallow "C." files
- X * NOTE: success return and file redirected to T: as this can
- X * occur only if somebody purposefully is trying to break us.
- X *
- X * Return 0 = success
- X */
- X
- Xint
- Xhost_send_file(msg)
- Xchar *msg;
- X{
- X FILE *fddsk; /* Disk file pointer */
- X char cmnd[1]; /* Command character */
- X int r;
- X int nor = 0;
- X
- X sscanf(msg,"%s %s %s %s %s %s %o",
- X cmnd, srcnam, dstnam, who, flags, temp, &mode);
- X
- X ulog(-1, "REQUESTED %s", msg);
- X munge_filename(dstnam, dstnam); /* Translate to local name */
- X strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
- X
- X if (SecurityDisallow(dstnam, 'w')) {
- X ulog(-1, "REQUEST FAILED -- SECURITY");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X if (SecurityDisallow(dstnam, 'c') > 0) {
- X ulog(-1, "REQUEST FAILED -- SECURITY, REMOTE TRIED TO SEND");
- X ulog(-1, "US A COMMAND FILE: %s, FILE COPIED TO T:Bad-Cmd", dstnam);
- X strcpy(dstnam, "T:Bad-Cmd");
- X nor = 1;
- X }
- X
- X /* FIXME: deal with file modes now that we fopen. */
- X
- X LockFile(temp);
- X
- X fddsk = fopen(temp, "wb" /*, mode|0600 */);
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* Can't open file -- send error response */
- X if (debug > 0) {
- X printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- X temp,
- X dstnam,
- X errno
- X );
- X }
- X ulog(-1, "REQUEST FAILED -- TEMP FILE");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X
- X /* FIXME: Are the above permissions right?? */
- X /* FIXME: Should we create directories for the file? */
- X
- X if (yesno('S',1, 0)) { /* Say yes */
- X fclose(fddsk);
- X unlink(temp);
- X UnLockFile(temp);
- X return 1;
- X }
- X r = receive_file(fddsk, temp, dstnam, srcnam, nor);
- X UnLockFile(temp);
- X return(r);
- X}
- X
- X/*
- X * SLAVE MODE, Master wants us to send a file to it
- X *
- X * SECURITY: If file is not in list of allowed directories
- X * disallow transfer. UUSPOOL: is always in the
- X * list.
- X *
- X * 0 = sucess
- X */
- X
- Xint
- Xhost_receive_file(msg)
- Xchar *msg;
- X{
- X FILE *fddsk; /* Disk file descriptor */
- X int x;
- X char cmnd[1]; /* Command character */
- X
- X ulog(-1, "REQUESTED %s", msg);
- X
- X sscanf(msg,"%s %s %s",cmnd,srcnam,dstnam);
- X munge_filename(srcnam, temp);
- X
- X if (SecurityDisallow(temp, 'r')) {
- X ulog(-1, "COPY FAILED -- SECURITY");
- X if (yesno('S', 0, 4))
- X return FAIL;
- X return SUCCESS;
- X }
- X
- X fddsk = fopen(temp, "rb"); /* Try to open the file */
- X if (fddsk == NULL) {
- X /* File didn't open, sigh. */
- X if (debug > 0) {
- X printf("Cannot open file %s (%s) for reading, errno=%d\n",
- X temp, srcnam, errno
- X );
- X }
- X ulog(-1, "DENIED CAN'T OPEN %s", temp);
- X if (yesno('R', 0, 2))
- X return 1;
- X return 0;
- X }
- X
- X if (yesno('R',1, 0)) { /* Say yes */
- X fclose(fddsk);
- X return 1;
- X }
- X
- X x = send_file(fddsk);
- X
- X switch (x) {
- X default:
- X return x;
- X case COPYFAIL:
- X /* We don't care if the copy failed, since the master
- X asked for the file and knows the result. */
- X return SUCCESS;
- X }
- X return 1;
- X}
- X
- X/*
- X * MASTER MODE, We want to send a file.
- X *
- X * Return FAIL, SUCCESS, or COPYFAIL.
- X *
- X * SUCCESS is returned either if the file was not found locally (local
- X * error, and the queued transfer should be flushed) or if it was moved
- X * successfully. COPYFAIL indicates that the queued transfer should be
- X * left queued, and later retried. FIXME, there are several failure points
- X * in the transaction (see Protocol.doc) and we need finer control here.
- X */
- X
- Xint
- Xlocal_send_file(workstr, delmeflag)
- Xchar *workstr;
- Xint *delmeflag;
- X{
- X static char buf[MAXMSGLEN]; /* Used for both xmit and receive */
- X FILE *fddsk; /* Disk file descriptor */
- X int res; /* Result and file removal status */
- X
- X *delmeflag = 0;
- X
- X /* WHY are temp and srcnam switched? FIXME! And no notify? */
- X
- X sprintf(buf,"S %s %s %s %s %s 0%o %s",
- X temp, dstnam, who, flags, srcnam, mode, who
- X );
- X
- X ulog(-1, "REQUEST %s", buf);
- X
- X if (strchr(flags, 'c')) {
- X munge_filename(srcnam, temp);
- X } else {
- X munge_filename(temp, temp);
- X }
- X LockFile(temp);
- X fddsk = fopen(temp, "rb");
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* FIXME -- handle queued request for nonexistent file */
- X if (debug > 0)
- X printf("Can't open file %s (%s), errno=%d\n",
- X temp,
- X srcnam,
- X errno
- X );
- X ulog(-1, "NOT FOUND %s", temp);
- X /* return COPYFAIL;*/
- X return SUCCESS; /* assume file previously sent */
- X }
- X
- X /* Tell the other side we want to send this file */
- X
- X if (wrmsg(buf) != SUCCESS) {
- X DEBUG(0, "problem sending request\n", 0);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X
- X /* See what they have to say about it */
- X
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X if ((buf[0] != 'S') || (buf[1] != 'Y')) {
- X ulog(-1, "REQUEST DENIED %s", buf);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X res = send_file(fddsk); /* FAIL, SUCCESS, or COPYFAIL */
- X
- X /* Delete the source file if it was just a copy */
- X
- X if (res != SUCCESS) {
- X UnLockFile(temp);
- X return res;
- X }
- X if (strchr(flags, 'c')) { /* If copied direct from source */
- X UnLockFile(temp);
- X return res; /* ...just return. */
- X }
- X *delmeflag = 1;
- X UnLockFile(temp);
- X
- X return res;
- X}
- X
- X/*
- X * MASTER MODE, We wish to receive a specific file so we ask for it
- X *
- X * Return 0 = success
- X */
- X
- Xint
- Xlocal_receive_file()
- X{
- X static char buf[MAXMSGLEN];
- X FILE *fddsk; /* Disk file pointer */
- X int r;
- X
- X /* FIXME, test dest file access before we ask for it. */
- X
- X sprintf(buf,"R %s %s %s %s %s 0%o %s",
- X srcnam, dstnam, who, flags, temp, mode, who
- X );
- X
- X munge_filename(dstnam, dstnam); /* tlate to local name */
- X strcpy (temp, TmpFileName(dstnam)); /* Create a handy temp file */
- X
- X /* FIXME: deal with file modes now that we fopen. */
- X /* FIXME: Are the above permissions right?? */
- X /* FIXME: Should we create directories for the file? */
- X
- X LockFile(temp);
- X fddsk = fopen(temp, "wb" /*, mode|060 */);
- X
- X if (fddsk == NULL) {
- X UnLockFile(temp);
- X /* Can't open temp file -- send error response */
- X if (debug > 0) {
- X printf("Cannot open temp file %s (%s) for writing, errno=%d\n",
- X temp,
- X dstnam,
- X errno
- X );
- X }
- X ulog(-1, "REQUEST FAILED -- TEMPFILE");
- X return FAIL;
- X }
- X
- X ulog(-1, "REQUEST %s", buf);
- X if (wrmsg(buf) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X printf("uucico: problem sending request\n");
- X return FAIL;
- X }
- X
- X /* See what the other side has to say about it */
- X
- X if (rdmsg(buf, MAXMSGLEN) != SUCCESS) {
- X fclose(fddsk);
- X UnLockFile(temp);
- X return FAIL;
- X }
- X if ((buf[0] != 'R') || (buf[1] != 'Y')) {
- X ulog(-1, "REQUEST DENIED %s", buf);
- X fclose(fddsk);
- X UnLockFile(temp);
- X return SUCCESS; /* FIXME, should do something more here */
- X }
- X
- X r = receive_file(fddsk, temp, dstnam, srcnam, 0);
- X UnLockFile(temp);
- X return(r);
- X}
- X
- X/*
- X * General receive file
- X */
- X
- Xint
- Xreceive_file(fddsk, temp, dstnam, srcnam, norename)
- XFILE *fddsk;
- Xchar *temp, *dstnam, *srcnam;
- X{
- X int status;
- X int error = 0; /* No errors so far */
- X
- X if (rddata(fddsk) != SUCCESS)
- X error++;
- X status = fclose(fddsk); /* Make sure the data got here */
- X if (status != 0) {
- X error++;
- X DEBUG(0, "fclose errno=%d\n", errno);
- X }
- X
- X /*
- X * Move the file from its temp location to its real location,
- X * This needs to be able to copy a file if a simple rename
- X * does not suffice. Should create directories if necesary.
- X * should use source ]name if target is a directory (i.e. no
- X * target source name
- X */
- X
- X unlink(dstnam);
- X
- X if (norename) /* for security redirect */
- X status = 0;
- X else
- X status = rename(temp, dstnam);
- X
- X if (status != 0) {
- X error++;
- X if (debug > 0) {
- X printf("Cannot rename file %s to %s, errno=%d\n",
- X temp, dstnam, errno);
- X }
- X }
- X
- X ulog(-1, "COPY %s", error ? "FAILED": "SUCCEEDED");
- X
- X if (yesno('C', error == 0, 5)) /* Send yes or no */
- X return FAIL;
- X
- X return SUCCESS;
- X}
- X
- X/*
- X * general file send routine
- X * Return SUCCESS, FAIL, or COPYFAIL.
- X */
- X
- Xint
- Xsend_file(fddsk)
- XFILE *fddsk; /* Disk file pointer */
- X{
- X static char ansbuf[MAXMSGLEN];
- X
- X if (wrdata(fddsk) != SUCCESS) {
- X fclose(fddsk);
- X return COPYFAIL;
- X }
- X fclose(fddsk);
- X
- X /* Await the "CY" or "CNddd" packet, and toss it. */
- X
- X while (1) {
- X if (rdmsg(ansbuf, MAXMSGLEN) != SUCCESS)
- X return COPYFAIL;
- X if (ansbuf[0] != 'C') {
- X DEBUG(0,"\nDidn't get 'CY' or 'CN', got %s\n", ansbuf);
- X /* and loop looking for C message */
- X } else if (ansbuf[1] == 'Y') {
- X ulog(-1, "REQUESTED %s", ansbuf);
- X return SUCCESS;
- X } else {
- X ulog(-1, "COPY FAILED %s", ansbuf);
- X return COPYFAIL;
- X }
- X }
- X return COPYFAIL;
- X}
- X
- END_OF_FILE
- if test 33705 -ne `wc -c <'uucp2/src/uucico/uucico.c'`; then
- echo shar: \"'uucp2/src/uucico/uucico.c'\" unpacked with wrong size!
- fi
- # end of 'uucp2/src/uucico/uucico.c'
- fi
- echo shar: End of archive 11 \(of 12\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 12 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general discussion to comp.sys.amiga.
-